
package cn.com.cifi.mars.activemq.consumer;

import static java.util.stream.Collectors.toList;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.concurrent.Executors;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONObject;

import cn.com.cifi.mars.bean.bo.SysLogBO;
import cn.com.cifi.mars.common.exception.MsgException;
import cn.com.cifi.mars.constant.ApprovedStateCodeEnum;
import cn.com.cifi.mars.constant.CollectTypeEnum;
import cn.com.cifi.mars.constant.Constants;
import cn.com.cifi.mars.constant.IsDeleteEnum;
import cn.com.cifi.mars.constant.IsSuccessEnum;
import cn.com.cifi.mars.constant.LogEventEnum;
import cn.com.cifi.mars.constant.LogSrcEnum;
import cn.com.cifi.mars.constant.LogTypeEnum;
import cn.com.cifi.mars.constant.ModifySourceTypeEunm;
import cn.com.cifi.mars.constant.ModuleTypeEunm;
import cn.com.cifi.mars.constant.OrgTypeEunm;
import cn.com.cifi.mars.constant.ProcessTypeEnum;
import cn.com.cifi.mars.constant.VersionEventEnum;
import cn.com.cifi.mars.constant.VersionStatusEnum;
import cn.com.cifi.mars.constant.VersionTypeEunm;
import cn.com.cifi.mars.entity.ApprovalBill;
import cn.com.cifi.mars.entity.ApprovalBillDetail;
import cn.com.cifi.mars.entity.ApprovalLog;
import cn.com.cifi.mars.entity.PriceVersion;
import cn.com.cifi.mars.entity.common.IdmUser;
import cn.com.cifi.mars.mapper.mars.ApprovalLogMapper;
import cn.com.cifi.mars.service.ApprovalBillDetailService;
import cn.com.cifi.mars.service.ApprovalBillService;
import cn.com.cifi.mars.service.ApprovalLogService;
import cn.com.cifi.mars.service.ApprovalPreviewService;
import cn.com.cifi.mars.service.ApprovalWarningSuperviseService;
import cn.com.cifi.mars.service.PriceApprovalCoreWarnService;
import cn.com.cifi.mars.service.PriceApprovalDifferencesBuildService;
import cn.com.cifi.mars.service.PriceApprovalDifferencesDetailService;
import cn.com.cifi.mars.service.PriceApprovalDifferencesService;
import cn.com.cifi.mars.service.PriceVersionService;
import cn.com.cifi.mars.service.ProjectReturnCoefficientService;
import cn.com.cifi.mars.service.ReturnPlanVersionService;
import cn.com.cifi.mars.service.SignPlanVersionDetailService;
import cn.com.cifi.mars.service.SignPlanVersionService;
import cn.com.cifi.mars.service.SubmitApprovedProjectService;
import cn.com.cifi.mars.service.SysLogService;
import cn.com.cifi.mars.service.VersionLogService;
import cn.com.cifi.mars.util.LocalDateTimeUtils;
import cn.com.cifi.mars.util.StrUtils;
import cn.com.cifi.mars.util.UUIDUtils;
import cn.com.cifi.mars.util.WebUtils;
import lombok.extern.slf4j.Slf4j;

/**
 * OA 消息队列接收
 * @author Administrator
 */
@Slf4j
@Component
public class OaMsgConsumer {

    @Autowired
    private SysLogService sysLogService;
    @Autowired
    private ApprovalBillService approvalBillService;
    @Autowired
    private ApprovalBillDetailService approvalBillDetailService;
    @Autowired
    private SubmitApprovedProjectService submitApprovedProjectService;
    @Autowired
    private PriceVersionService priceVersionService;
    @Autowired
    private SignPlanVersionService signPlanVersionService;
    @Autowired
    private ApprovalLogService approvalLogService;
    @Autowired
    private ApprovalLogMapper approvalLogMapper;
    @Autowired
    private VersionLogService versionLogService;
    @Autowired
	private SignPlanVersionDetailService signPlanVersionDetailService;
    @Autowired
	private ProjectReturnCoefficientService  projectReturnCoefficientService;
    @Autowired
	private ReturnPlanVersionService returnPlanVersionService;
    @Autowired
    private ApprovalWarningSuperviseService approvalWarningSuperviseService;
    @Autowired
    private ApprovalPreviewService approvalPreviewService;
    @Autowired
    private PriceApprovalCoreWarnService priceApprovalCoreWarnService;
    @Autowired
    private PriceApprovalDifferencesService priceApprovalDifferencesService;
    @Autowired
    private PriceApprovalDifferencesDetailService priceApprovalDifferencesDetailService;
    @Autowired
    private PriceApprovalDifferencesBuildService priceApprovalDifferencesBuildService;
    
    
    @JmsListener(destination = "${oa_queue}", containerFactory = "oaFactory")
    public void receiveMsg(String msg) {
    	log.info("###############OA消息接收   Start: "+ LocalDateTime.now());
    	try {
    		saveLog("OA消息接收", "OA消息数据", msg, IsSuccessEnum.SUCCESS.getKey());
			
			if (StringUtils.isEmpty(msg)) {
				log.info("OA消息数据为空");
				return;
			}
			// 1.解析json
			JSONObject parseObject = JSONObject.parseObject(msg);
			// 事件类型 0:实例已删除 3:流程发起 4:审批通过 5:驳回发起人 6:发起人撤回
			//oa审批状态
			Integer eventType = parseObject.getIntValue("eventType");
			//审批单主键id
			String businesskey = parseObject.getString("businesskey");
			//任务id
			String taskId = parseObject.getString("taskId");
			//操作人账号
			String operatorAccount = parseObject.getString("operatorAccount");
			//转换单据状态
			String status = prepareBillStatus(eventType);
			//校验审批单
			ApprovalBill approvalBill = checkApprovalBill(businesskey,status,msg);
			if(null == approvalBill || StringUtils.isBlank(status)){
				return;
			}
			saveApprovalLog(businesskey,status,msg,"接收MQ消息，处理单据状态");
			//更新审批单状态
			approvalBillService.updateByOA(businesskey,taskId,status);
			//处理其他数据(数据快照)
			handleOtherData(approvalBill,status);
			//处理业务数据
			handleBusinessData(approvalBill,eventType,operatorAccount);
		} catch (Exception e) {
			saveLog("OA消息接收", "OA消息数据", e.getMessage(),IsSuccessEnum.FAIL.getKey());
			log.error("####OA消息数据失败", e);
		}
    	log.info("###############OA消息接收   End: "+ LocalDateTime.now());
    }


	/**
	 * 处理业务数据
	 * @param approvalBill 审批单
	 * @param eventType oa审批状态
	 * @param operatorAccount 操作人账号
	 */
	private void handleBusinessData(ApprovalBill approvalBill, Integer eventType, String operatorAccount) {
		String id = approvalBill.getId();
		String businessType = approvalBill.getBusinessType();
		String approvalState = approvalBill.getState();
		String versionState = prepareVersionStatus(eventType);
        String versionEvent = VersionEventEnum.toVersionEvent(eventType);
        String projectId = approvalBill.getProjectId();
        //查询本次审批的所有分期版本信息
		List<ApprovalBillDetail> approvalBillDetails = approvalBillDetailService.selectApprovalBillDetail(id);
		if (CollectionUtils.isEmpty(approvalBillDetails)) {
			return;
		}
		//根据各业务类型,做数据处理
		if(businessType.equals(ProcessTypeEnum.PRICE_MANAGEMENT.getKey())) {
			List<String> versionIds = approvalBillDetails.stream().map(ApprovalBillDetail::getVersionId).collect(toList());
			//记录版本日志
			saveVersionLog(approvalBill.getId(),operatorAccount,ProcessTypeEnum.PRICE_MANAGEMENT.getKey(),approvalState);
			try {
				//修改货值版本审批状态
				priceVersionService.updateStateById(versionIds,versionState,operatorAccount);
			} catch (MsgException msg) {
				log.info("##########"+msg.getMessage());
			}
			//货值预警发送待办
			if(eventType.intValue() == Constants.THREE || eventType.intValue() == Constants.FOUR) {
				try {
					approvalWarningSuperviseService.sendWarningSupervise(id,eventType);
				} catch (Exception e) {
					log.info("##########发送预警待办 异常");
					e.printStackTrace();
				}
			}
			//删除货值预警发送待办
			if(eventType.intValue() == Constants.FIVE || eventType.intValue() == Constants.SIX) {
				try {
					approvalPreviewService.cleanPriceWarnTodo(id,null);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			
			//审批通过后解析并保存EXCEL数据
			if(eventType.intValue() == Constants.FOUR) {
				savePriceExcelData(id, versionState, projectId);
			}
			saveLog("OA消息接收", "更新货值版本状态", "单据ID：" + approvalBill.getId() + "；货值版本ID："+versionIds.toString()+"；状态更新为：" + versionState, IsSuccessEnum.SUCCESS.getKey());
		}else if(businessType.equals(ProcessTypeEnum.SIGNING_PLAN.getKey())) {
			for (ApprovalBillDetail approvalBillDetail : approvalBillDetails) {
				String versionId = approvalBillDetail.getVersionId();
				//调用签约接口,
				signPlanVersionService.successSpproved(versionId,versionState,eventType);
				if(VersionStatusEnum.SUCCESSAPPROVED.getKey().equals(versionState)){
					//推送Esb接口-费控系统
					Executors.newCachedThreadPool().submit(() -> {
						signPlanVersionDetailService.sendSignPlan(versionId,2);
					});
					
					//复制预算版本
					Executors.newCachedThreadPool().submit(() -> {
						signPlanVersionDetailService.autoCopySignPlanVersion(versionId);
					});
				}
				saveLog("OA消息接收", "更新签约版本状态", "单据ID：" + approvalBill.getId() + "；签约版本ID："+versionId+"；状态更新为：" + versionState , IsSuccessEnum.SUCCESS.getKey());
			}
		}else if (businessType.equals(ProcessTypeEnum.MONEY_BACK_COEFFICIENT.getKey())){
			for (int i = 0; i < approvalBillDetails.size(); i++) {
				String versionId = approvalBillDetails.get(i).getVersionId();
				//调用回款系数接口,
				projectReturnCoefficientService.successServed(versionId,versionState,LocalDateTime.now());
				saveLog("OA消息接收", "更新回款系数调整板版本状态", "单据ID：" + approvalBill.getId() + "；版本ID："+versionId+"；状态更新为：" + versionState , IsSuccessEnum.SUCCESS.getKey());
			}
		}else if (businessType.equals(ProcessTypeEnum.MONEY_BACK_PLAN.getKey())){
            List<String> versionId = approvalBillDetails.stream().map(ApprovalBillDetail::getVersionId).collect(toList());
            IdmUser user = new IdmUser();
            user.setAlias(Constants.SYS);
            returnPlanVersionService.updateState(versionId,versionEvent,versionState,user);
		}

	}


	public void savePriceExcelData(String id, String versionState, String projectId) {
		try {
			//保存货值审批全盘概览数据
			priceApprovalDifferencesService.saveData(id);
			//保存货值审批全盘差异详情数据
			priceApprovalDifferencesDetailService.saveData(id,projectId,versionState);
			//保存货值审批本次调价楼栋数据
			priceApprovalDifferencesBuildService.savePriceApprovalDifferencesBuildData(id,projectId,versionState);
			//保存货值审批核心指标数据
			priceApprovalCoreWarnService.savePriceApprovalCoreWarnData(id,projectId,versionState);
		} catch (Exception e) {
			log.info("##########解析数据 异常");
			e.printStackTrace();
		}
	}


	/**
	 * 处理其他数据
	 * @param approvalBill
	 * @param approvalState
	 */
	private void handleOtherData(ApprovalBill approvalBill, String approvalState) {
		String approvalId = approvalBill.getId();
		//1、货值快照
		if(ApprovedStateCodeEnum.APPROVAL.getKey().equals(approvalState)){
			List<String> ids = submitApprovedProjectService.selectVersionIdByKey(approvalId,CollectTypeEnum.ADJUST_AFTER.getKey());
			submitApprovedProjectService.saveApprovedShot(ids, OrgTypeEunm.ORG_STAGE.getKey(), approvalId);
		}
		//2、对签约审批单查看内容缓存处理
		if(approvalBill.getBusinessType().equals(ProcessTypeEnum.SIGNING_PLAN.getKey())){
			signPlanVersionService.handApprovalBillBuffer(approvalId,approvalState);
		}
	}

	/**
	 * 校验审批单
	 * @param businesskey
	 * @param status
	 * @param msg
	 * @return
	 */
	private ApprovalBill checkApprovalBill(String businesskey, String status, String msg) {
		//查询审批单
		ApprovalBill approvalBill1 = submitApprovedProjectService.selectApprovalBillByKey(businesskey);
		if(null != approvalBill1){
			//获取最近一条审批单记录
			ApprovalLog approvalLog = approvalLogMapper.selectOneByBillId(businesskey);
			//判断审批单是否是结束状态
			if(approvalLog != null ) {
				if("OA".equals(approvalLog.getSource())) {
					String state = approvalLog.getState();
					if(state.equals(ApprovedStateCodeEnum.DELETE.getKey()) || state.equals(ApprovedStateCodeEnum.APPROVAL_SUCCESS.getKey())) {
						//审批单日志
						saveApprovalLog(businesskey,status,msg,"该审批单已是结束节点，mq消息延迟");
					}
				}
			}
		}
		return approvalBill1;
	}


	/**
	 * 
	 * @Description：转换单据状态
	 * @param eventType 事件code
	 * @return String
	 * @author：yyd
	 * @date：2020年3月26日 上午12:01:51
	 */
    private String prepareBillStatus(Integer eventType) {
    	String status = "";
    	switch (eventType.intValue()) {
		case Constants.ZERO:
			status = ApprovedStateCodeEnum.DELETE.getKey();
			break;
		case Constants.THREE:
			status = ApprovedStateCodeEnum.APPROVAL.getKey();
			break;
		case Constants.FOUR:
			status = ApprovedStateCodeEnum.APPROVAL_SUCCESS.getKey();
			break;
		case Constants.FIVE:
			status = ApprovedStateCodeEnum.REJECT.getKey();
			break;
		case Constants.SIX:
			status = ApprovedStateCodeEnum.RECALL.getKey();
			break;
		default:
			break;
		}
    	return status;
    }
    /**
	 * 
	 * @Description：转换版本状态
	 * @param eventType 事件code
	 * @return String
	 * @author：yyd
	 * @date：2020年3月26日 上午12:01:51
	 */
    private String prepareVersionStatus(Integer eventType) {
    	String state ="";
    	switch (eventType.intValue()) {
		case Constants.ZERO:
			state = VersionStatusEnum.ORGANIZATION.getKey();
			break;
		case Constants.THREE:
			state = VersionStatusEnum.APPROVED.getKey();
			break;
		case Constants.FOUR:
			state = VersionStatusEnum.SUCCESSAPPROVED.getKey();
			break;
		case Constants.FIVE:
			state = VersionStatusEnum.FAILUREAPPROVED.getKey();
			break;
		case Constants.SIX:
			state = VersionStatusEnum.EXAMINEDAPPROVED.getKey();
			break;
		default:
			break;
		}
    	return state;
    }
    
    private void saveApprovalLog(String businessKey, String state,String res,String desc) {
		ApprovalLog approvalLog = new ApprovalLog();
		approvalLog.setId(UUIDUtils.create());
		approvalLog.setBillId(businessKey);
		approvalLog.setState(state);
		approvalLog.setSource("OA");
		approvalLog.setContent(res);
		approvalLog.setDescription(desc);
		approvalLog.setCreatedTime(LocalDateTime.now());
		approvalLogService.add(approvalLog);
	}
    
    private void saveVersionLog(String instanceId,String alias, String processType,String status) {
    	if(processType.equals(ProcessTypeEnum.PRICE_MANAGEMENT.getKey())) {
    		String beforeState="";
    		String afterState= "";
    		String event="";
    		if(status.equals(ApprovedStateCodeEnum.DELETE.getKey())) {
    			event = VersionEventEnum.APPROVAL_NO_ADOPT.getKey();
    			afterState = VersionStatusEnum.ORGANIZATION.getKey();
    		}else if(status.equals(ApprovedStateCodeEnum.APPROVAL.getKey())) {
    			event = VersionEventEnum.TO_OA_APPROVED.getKey();
    			afterState = VersionStatusEnum.APPROVED.getKey();
    		}else if(status.equals(ApprovedStateCodeEnum.APPROVAL_SUCCESS.getKey())) {
    			event = VersionEventEnum.APPROVAL_ADOPT.getKey();
    			beforeState = VersionStatusEnum.APPROVED.getKey();
    			afterState= VersionStatusEnum.SUCCESSAPPROVED.getKey();
    		}else if(status.equals(ApprovedStateCodeEnum.REJECT.getKey())) {
    			event = VersionEventEnum.APPROVAL_NO_ADOPT.getKey();
    			afterState= VersionStatusEnum.FAILUREAPPROVED.getKey();
    		}else if(status.equals(ApprovedStateCodeEnum.RECALL.getKey())) {
    			event = VersionEventEnum.APPROVAL_NO_ADOPT.getKey();
    			afterState= VersionStatusEnum.EXAMINEDAPPROVED.getKey();
    		}
    		List<PriceVersion> list = submitApprovedProjectService.selectVersionByBillId(instanceId);
        	if(CollectionUtils.isNotEmpty(list)) {
        		for(PriceVersion version : list) {
        			if(version != null) {
        				String versionName = prepareVersionName(version.getVersionType(),
            					version.getVersionNum(),version.getIsAssessmentVersion(),
            					version.getAscriptionDate(),version.getUpdateTime(),status);
            			
        				if(!status.equals(ApprovedStateCodeEnum.APPROVAL_SUCCESS.getKey())) {
            				beforeState = version.getVersionState();
            			}
        				versionLogService.saveVersionLogInfo(version.getProjectId(),version.getProjectfId(),ModuleTypeEunm.PRICE.getKey(),
        						event,version.getId(),versionName,beforeState,afterState,ModifySourceTypeEunm.TWO.getKey(),
        						version.getId(),alias,LocalDateTime.now(),"货值审批","货值审批",IsDeleteEnum.NO.getKey(),alias,LocalDateTime.now());
        			}
        		}
        	}
    	}
	}
    
    private String prepareVersionName(String versionType,String vesionNum,
			Integer isAssessmentVersion,LocalDate affiliationMonth,
			LocalDateTime updateTime,String status) {
		String versionName="";
		String versionTypeName = VersionTypeEunm.getValueByKey(versionType);
		String lastDate = "";
		if(status.equals(ApprovedStateCodeEnum.APPROVAL_SUCCESS.getKey()) && updateTime != null) {
			lastDate = LocalDateTimeUtils.formatTime(updateTime, "yyyyMMdd");
		}
		if(versionType.equals(VersionTypeEunm.INVESTMENT.getKey()) || versionType.equals(VersionTypeEunm.WARPLAN.getKey()) 
				|| versionType.equals(VersionTypeEunm.GETPRICE.getKey())) {
			String assessmentTag="";
			if(isAssessmentVersion != null && isAssessmentVersion.intValue() == 1) {
				assessmentTag = "(考核版)";
			}
			if(StrUtils.isEmpty(lastDate)) {
				versionName = versionTypeName+vesionNum+assessmentTag;
	        }else {
	        	versionName = versionTypeName+vesionNum+"-"+lastDate+assessmentTag;
	        }
		}else {
			if(affiliationMonth != null) {
				DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyyMM");
		        String dateStr = affiliationMonth.format(fmt);
		        if(StrUtils.isEmpty(lastDate)) {
		        	versionName = dateStr+"月动态版"+vesionNum;
		        }else {
		        	versionName = dateStr+"月动态版"+vesionNum+"-"+lastDate;
		        }
			}
		}
		return versionName;
	}
    
	private void saveLog(String module,String title,String content,String isSuccess) {
        SysLogBO bo = new SysLogBO();
        bo.setEvent(LogEventEnum.MQ);
        bo.setSource(LogSrcEnum.SYS);
        String hostAddr =WebUtils.getLocalIP();
        bo.setIp(hostAddr);
        bo.setModule(module);
        bo.setTitle(title);
        bo.setContent(content);
        bo.setType(LogTypeEnum.ONE.getKey());
        bo.setIsSuccess(isSuccess);
        sysLogService.add(bo,Constants.SYS);
    }
}

